#pragma once

#include"../source/server.hpp"
#include<fstream>
#include<sys/stat.h>
#include<regex>

std::unordered_map<int,std::string> _status_map={
    {100, "Continue"},
    {101, "Switching Protocol"},
    {102, "Processing"},
    {103, "Early Hints"},
    {200, "OK"},
    {201, "Created"},
    {202, "Accepted"},
    {203, "Non-Authoritative Information"},
    {204, "No Content"},
    {205, "Reset Content"},
    {206, "Partial Content"},
    {207, "Multi-Status"},
    {208, "Already Reported"},
    {226, "IM Used"},
    {300, "Multiple Choice"},
    {301, "Moved Permanently"},
    {302, "Found"},
    {303, "See Other"},
    {304, "Not Modified"},
    {305, "Use Proxy"},
    {306, "unused"},
    {307, "Temporary Redirect"},
    {308, "Permanent Redirect"},
    {400, "Bad Request"},
    {401, "Unauthorized"},
    {402, "Payment Required"},
    {403, "Forbidden"},
    {404, "Not Found"},
    {405, "Method Not Allowed"},
    {406, "Not Acceptable"},
    {407, "Proxy Authentication Required"},
    {408, "Request Timeout"},
    {409, "Conflict"},
    {410, "Gone"},
    {411, "Length Required"},
    {412, "Precondition Failed"},
    {413, "Payload Too Large"},
    {414, "URI Too Long"},
    {415, "Unsupported Media Type"},
    {416, "Range Not Satisfiable"},
    {417, "Expectation Failed"},
    {418, "I'm a teapot"},
    {421, "Misdirected Request"},
    {422, "Unprocessable Entity"},
    {423, "Locked"},
    {424, "Failed Dependency"},
    {425, "Too Early"},
    {426, "Upgrade Required"},
    {428, "Precondition Required"},
    {429, "Too Many Requests"},
    {431, "Request Header Fields Too Large"},
    {451, "Unavailable For Legal Reasons"},
    {501, "Not Implemented"},
    {502, "Bad Gateway"},
    {503, "Service Unavailable"},
    {504, "Gateway Timeout"},
    {505, "HTTP Version Not Supported"},
    {506, "Variant Also Negotiates"},
    {507, "Insufficient Storage"},
    {508, "Loop Detected"},
    {510, "Not Extended"},
    {511, "Network Authentication Required"}
};


 std::unordered_map<std::string,std::string> _ext_mime={
    {".aac", "audio/aac"},
    {".abw", "application/x-abiword"},
    {".arc", "application/x-freearc"},
    {".avi", "video/x-msvideo"},
    {".azw", "application/vnd.amazon.ebook"},
    {".bin", "application/octet-stream"},
    {".bmp", "image/bmp"},
    {".bz", "application/x-bzip"},
    {".bz2", "application/x-bzip2"},
    {".csh", "application/x-csh"},
    {".css", "text/css"},
    {".csv", "text/csv"},
    {".doc", "application/msword"},
    {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
    {".eot", "application/vnd.ms-fontobject"},
    {".epub", "application/epub+zip"},
    {".gif", "image/gif"},
    {".htm", "text/html"},
    {".html", "text/html"},
    {".ico", "image/vnd.microsoft.icon"},
    {".ics", "text/calendar"},
    {".jar", "application/java-archive"},
    {".jpeg", "image/jpeg"},
    {".jpg", "image/jpeg"},
    {".js", "text/javascript"},
    {".json", "application/json"},
    {".jsonld", "application/ld+json"},
    {".mid", "audio/midi"},
    {".midi", "audio/x-midi"},
    {".mjs", "text/javascript"},
    {".mp3", "audio/mpeg"},
    {".mpeg", "video/mpeg"},
    {".mpkg", "application/vnd.apple.installer+xml"},
    {".odp", "application/vnd.oasis.opendocument.presentation"},
    {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
    {".odt", "application/vnd.oasis.opendocument.text"},
    {".oga", "audio/ogg"},
    {".ogv", "video/ogg"},
    {".ogx", "application/ogg"},
    {".otf", "font/otf"},
    {".png", "image/png"},
    {".pdf", "application/pdf"},
    {".ppt", "application/vnd.ms-powerpoint"},
    {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
    {".rar", "application/x-rar-compressed"},
    {".rtf", "application/rtf"},
    {".sh", "application/x-sh"},
    {".svg", "image/svg+xml"},
    {".swf", "application/x-shockwave-flash"},
    {".tar", "application/x-tar"},
    {".tif", "image/tiff"},
    {".tiff", "image/tiff"},
    {".ttf", "font/ttf"},
    {".txt", "text/plain"},
    {".vsd", "application/vnd.visio"},
    {".wav", "audio/wav"},
    {".weba", "audio/webm"},
    {".webm", "video/webm"},
    {".webp", "image/webp"},
    {".woff", "font/woff"},
    {".woff2", "font/woff2"},
    {".xhtml", "application/xhtml+xml"},
    {".xls", "application/vnd.ms-excel"},
    {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
    {".xml", "application/xml"},
    {".xul", "application/vnd.mozilla.xul+xml"},
    {".zip", "application/zip"},
    {".3gp", "video/3gpp"},
    {".3g2", "video/3gpp2"},
    {".7z", "application/x-7z-compressed"}
    };
#define DEFAULT_TIMEOUT 10 //默认超时时间30秒
//零碎的功能接口
class Util{
    public:
        //字符串分割函数,将src按照sep分割，分割出的子串放入数组arry，返回值是分割出的子串个数
        static size_t Split(const std::string&src,const std::string&sep,std::vector<std::string>*arry){
            int count=0;
            int offset=0;
            size_t pos=src.find(sep,offset);
            while(pos!=std::string::npos){
                if(offset<pos)
                arry->push_back(src.substr(offset,pos-offset));
                offset=pos+sep.size();
                pos=src.find(sep,offset);
                count++;
            }
             if(offset<src.size())
            arry->push_back(src.substr(offset));
            return arry->size();
        }
        //读取文件的所有内容，将读取内容放到buffer中
        static bool ReadFile(const std::string&filename,std::string*buffer){
            std::ifstream ifs(filename.c_str(),std::ios::binary);
            if(!ifs.is_open()){
                ERR_LOG("open file failed:%s",filename.c_str());
                return false;
            }
            size_t fsize=0;
            ifs.seekg(0,std::ios::end);
            fsize=ifs.tellg();
            ifs.seekg(0,std::ios::beg);
            std::string content;
            content.resize(fsize);
            ifs.read(&content[0],fsize);
            if(ifs.good()==false){
                ERR_LOG("read file failed:%s",filename.c_str());
                ifs.close();
                return false;
            }
            buffer->swap(content);
            ifs.close();
            return true;
        }
        //写入文件
        static bool WriteFile(const std::string&filename,const std::string&buf){
            std::ofstream ofs(filename.c_str(),std::ios::binary|std::ios::trunc);
            if(!ofs.is_open()){
                ERR_LOG("open file failed:%s",filename.c_str());
                return false;
            }
            ofs.write(buf.c_str(),buf.size());
            if(ofs.good()==false){
                ERR_LOG("write file failed:%s",filename.c_str());
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }
        //url编码,避免URL中资源路径和查询字符串中的特殊字符与HTTP请求中特殊字符产生歧义
        // 不用编码的字符：RFC 3986定义的如下 . - _ ~ 字母 数字
        //RFC3986规定转换格式：%HH
        // W3C格式规定查询字符串的空格要转化为+
        static std::string UrlEncode(const std::string&url,bool  convert_space_to_plus){
            std::string result;
            for(auto c:url)
            {
                if(c=='.'||c=='-'||c=='_'||c=='~'||('0'<=c&&c<='9')||('a'<=c&&c<='z')||('A'<=c&&c<='Z')){
                    result+=c;
                }
                else if(c==' '&&convert_space_to_plus){
                    result+='+';
                }
                else{
                    char tmp[4]={0};
                    sprintf(tmp,"%%%02X",(unsigned char)c);
                    result+=tmp;
                }
            }
            return result;
        }
        static int HEXTOI(char c){
            if(c>='0'&&c<='9')
                return c-'0';
            if(c>='a'&&c<='f')
                return c-'a'+10;
            if(c>='A'&&c<='F')
                return c-'A'+10;
            return -1;
        }
        //url解码
        static std::string UrlDecode(const std::string&url,bool convert_plus_to_space){
            std::string result;
            for(auto i=0;i<url.size();i++){
                if(url[i]=='%'){
                    if(i+2>=url.size()){
                        ERR_LOG("url decode failed:%s",url.c_str());
                        return "";
                    }
                    char tmp=HEXTOI(url[i+1])*16+HEXTOI(url[i+2]);
                    result+=tmp;
                    i+=2;
                }
                else if(url[i]=='+'&&convert_plus_to_space){
                    result+=' ';
                }
                else{
                    result+=url[i];
                }
            }
            return result;
        }
        //响应状态码的描述信息获取
        static std::string StatuDesc(int status){
            auto it=_status_map.find(status);
            if(it!=_status_map.end())
                return it->second;
            return "UnKonwn Status";
        }
        //根据文件后缀名获取mime
        static std::string ExtMime(std::string&filename){
            std::unordered_map<std::string,std::string> _ext_mime={{".aac", "audio/aac"},
            {".abw", "application/x-abiword"},
            {".arc", "application/x-freearc"},
            {".avi", "video/x-msvideo"},
            {".azw", "application/vnd.amazon.ebook"},
            {".bin", "application/octet-stream"},
            {".bmp", "image/bmp"},
            {".bz", "application/x-bzip"},
            {".bz2", "application/x-bzip2"},
            {".csh", "application/x-csh"},
            {".css", "text/css"},
            {".csv", "text/csv"},
            {".doc", "application/msword"},
            {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {".eot", "application/vnd.ms-fontobject"},
            {".epub", "application/epub+zip"},
            {".gif", "image/gif"},
            {".htm", "text/html"},
            {".html", "text/html"},
            {".ico", "image/vnd.microsoft.icon"},
            {".ics", "text/calendar"},
            {".jar", "application/java-archive"},
            {".jpeg", "image/jpeg"},
            {".jpg", "image/jpeg"},
            {".js", "text/javascript"},
            {".json", "application/json"},
            {".jsonld", "application/ld+json"},
            {".mid", "audio/midi"},
            {".midi", "audio/x-midi"},
            {".mjs", "text/javascript"},
            {".mp3", "audio/mpeg"},
            {".mpeg", "video/mpeg"},
            {".mpkg", "application/vnd.apple.installer+xml"},
            {".odp", "application/vnd.oasis.opendocument.presentation"},
            {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
            {".odt", "application/vnd.oasis.opendocument.text"},
            {".oga", "audio/ogg"},
            {".ogv", "video/ogg"},
            {".ogx", "application/ogg"},
            {".otf", "font/otf"},
            {".png", "image/png"},
            {".pdf", "application/pdf"},
            {".ppt", "application/vnd.ms-powerpoint"},
            {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {".rar", "application/x-rar-compressed"},
            {".rtf", "application/rtf"},
            {".sh", "application/x-sh"},
            {".svg", "image/svg+xml"},
            {".swf", "application/x-shockwave-flash"},
            {".tar", "application/x-tar"},
            {".tif", "image/tiff"},
            {".tiff", "image/tiff"},
            {".ttf", "font/ttf"},
            {".txt", "text/plain"},
            {".vsd", "application/vnd.visio"},
            {".wav", "audio/wav"},
            {".weba", "audio/webm"},
            {".webm", "video/webm"},
            {".webp", "image/webp"},
            {".woff", "font/woff"},
            {".woff2", "font/woff2"},
            {".xhtml", "application/xhtml+xml"},
            {".xls", "application/vnd.ms-excel"},
            {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {".xml", "application/xml"},
            {".xul", "application/vnd.mozilla.xul+xml"},
            {".zip", "application/zip"},
            {".3gp", "video/3gpp"},
            {".3g2", "video/3gpp2"},
            {".7z", "application/x-7z-compressed"}
            };
            auto it=_ext_mime.find(filename.substr(filename.rfind('.')));
            if(it!=_ext_mime.end())
                return it->second;
            return "application/octet-stream";//二进制流文件
        }
        // 判断一个文件是不是目录
        static bool IsDirectory(const std::string&filename){
            struct stat st;
            int ret=stat(filename.c_str(),&st);
            if(ret<0){
                return false;
            }
            return S_ISDIR(st.st_mode);
        }
        //判断一个文件是不是普通文件
        static bool IsRegular(std::string&filename){
            struct stat st;
            int ret=stat(filename.c_str(),&st);
            if(ret<0){
                return false;
            }
            return S_ISREG(st.st_mode);
        }
        //http请求资源的有效性判断
        static bool ValidPath(const std::string&path){
            //按照/进行路径分割，计算路径深度，如果最低层次低于0，则认为是非法路径
            std::vector<std::string> arry;
            Split(path,"/",&arry);
            int depth=0;
            for(auto&s:arry){
                if(s==".."){
                    depth--;
                    if(depth<0)
                        return false;
                }
                else if(s!=".")
                    depth++;
                }
            return true;
        }
        //
};



class HttpRequest{
    public://为了便于访问成员变量，将成员变量全部声明为public
        std::string _method;//请求方法
        std::string _path;//请求路径
        std::string _version="HTTP/1.1";//http版本
        std::string _body;//正文
        std::smatch _matchs;//URL的正则提取结果
        std::unordered_map<std::string,std::string> _headers;//请求头
        std::unordered_map<std::string,std::string> _params;//查询字符串
    public:
        HttpRequest():_version("HTTP/1.1"){}
        void ReSet(){
            _method.clear();
            _path.clear();
            _version.clear();
            _body.clear();
            std::smatch match;
            _matchs.swap(match);
            _headers.clear();
            _params.clear();
        }
        //插入头部字段
        void SetHeader(std::string&key,std::string&value){
            _headers[key]=value;
        }
        // 判断是否存在指定头部字段
        bool HasHeader(std::string&key){
            return _headers.find(key)!=_headers.end();
        }
        // 获取指定头部字段的值
        std::string GetHeader(std::string&key){
            if(HasHeader(key)){
                return _headers[key];
            }
            return "";
        }
        //插入查询字符串参数
        void SetParam(std::string&key,std::string&value){
            _params[key]=value;
        }
        //判断是否存在指定查询字符串参数
        bool HasParam(std::string&key){
            return _params.find(key)!=_params.end();
        }
        //获取指定查询字符串参数的值
        std::string GetParam(std::string&key){
            if(HasParam(key)){
                return _params[key];
            }
            return "";
        }
        //获取请求体的长度
        size_t ContentLength(){
            std::string content_length="Content-Length";
            if(HasHeader(content_length)){
                return std::stoll(GetHeader(content_length));
            }
            return 0;
        }
        //判断是不是短链接
        bool Close(){
            std::string s="Connection";
            if(HasHeader(s)&&(GetHeader(s)=="keep-alive"))
                return false;
            return true;
        }
};


class HttpResponse{
    public:
        int _statu;//响应状态码
        bool _redirect_flag;//是否是重定向
        std::string _redirect_url;//重定向的url
        std::unordered_map<std::string,std::string> _headers;//响应头部
        std::string _body;//响应正文
    public:
        HttpResponse(int status=200):_redirect_flag(false),_statu(status){}
        void ReSet(){
            _statu=200;
            _redirect_flag=false;
            _redirect_url.clear();
            _headers.clear();
            _body.clear();
        }
        void SetHeader(const std::string&key,const std::string&value){
            _headers[key]=value;
        }
        // 判断是否存在指定头部字段
        bool HasHeader(const std::string&key){
            return _headers.find(key)!=_headers.end();
        }
        // 获取指定头部字段的值
        std::string GetHeader(const std::string&key){
            if(HasHeader(key)){
                return _headers[key];
            }
            return "";
        }
        void SetContent(const std::string&content,const std::string&type){
            _headers["Content-Type"]=type;
            _body=content;
        }
        void SetRedirect(const std::string&url,int status=302){
            _redirect_flag=true;
            _redirect_url=url;
            _statu=status;
        }
        bool Close(){
            std::string s="Connection";
            if(HasHeader(s)&&GetHeader(s)==std::string("keep-alive"))
            return false;
            return true;
        }
};

#define MAX_LINE 1024*8//最大一行数据大小8kb
typedef enum{RECV_HTTP_ERR,RECV_HTTP_LINE,RECV_HTTP_HEAD,RECV_HTTP_BODY,RECV_HTTP_OVER}HttpRecvStatu;
class HttpContext{
    private:
        int _resp_statu;//响应状态码
        HttpRecvStatu _recv_statu;//当前接受及解析的状态
        HttpRequest _request;//已经解析得到的请求信息
    private:
        bool RecvHttpLine(Buffer*buf){
            if(_recv_statu!=RECV_HTTP_LINE)return false;
            std::string line;
            line=buf->GetLineAndPop();
            if(line.empty()){
                //缓冲区不足一行(无'\n)
                //判断缓冲区数据大小，如果缓冲区数据很多还没有一行就说明有问题
                if(buf->ReadAbleSize()>MAX_LINE)
                {
                    _resp_statu=414;//请求实体过长
                    _recv_statu=RECV_HTTP_ERR;
                    return false;
                }
                return true;
            }
            if(line.size()>MAX_LINE)
            {
                _resp_statu=414;//请求实体过长
                _recv_statu=RECV_HTTP_ERR;
                    return false;
            }
            int ret=ParseHttpLine(line);
            _recv_statu=RECV_HTTP_HEAD;
            return ret;
        }
        bool ParseHttpLine(std::string&line){
            if(_recv_statu!=RECV_HTTP_LINE)return false;
            std::smatch match;
            std::regex e("(GET|HEAD|POST|PUT|DELETE) ([^?]*)(?:\\?(.*))? (HTTP/1\\.[01])(?:\n|\r\n)?",std::regex::icase);
            bool ret=std::regex_match(line,match,e);
            if(!ret){
                _recv_statu=RECV_HTTP_ERR;
                _resp_statu=400;//请求语法错误
                return false;
            }
            _request._method=match[1];
            transform(_request._method.begin(),_request._method.end(),_request._method.begin(),::toupper);
            _request._path=Util::UrlDecode(match[2],false);
            _request._version=match[4];
            if(match[3].length()>0){
                std::vector<std::string> arry;
                Util::Split(match[3],"&",&arry);
                for(auto&s:arry){
                    int pos=s.find('=');
                    if(pos==std::string::npos){
                        _recv_statu=RECV_HTTP_ERR;
                        _resp_statu=400;//请求语法错误
                        return false;
                    }
                    std::string key=Util::UrlDecode(s.substr(0,pos),1);
                    std::string value=Util::UrlDecode(s.substr(pos+1),1);
                    _request.SetParam(key,value);
                }
            }
            return true;
        }
        bool RecvHttpHead(Buffer*buf){
            if(_recv_statu!=RECV_HTTP_HEAD)return false;
            while(1){
            std::string line;
            line=buf->GetLineAndPop();
            if(line=="\r\n"||line=="\n")break;
            if(line.empty()){
                //缓冲区不足一行(无'\n)
                //判断缓冲区数据大小，如果缓冲区数据很多还没有一行就说明有问题
                if(buf->ReadAbleSize()>MAX_LINE)
                {
                    _resp_statu=414;//请求实体过长
                    _recv_statu=RECV_HTTP_ERR;
                    return false;
                }
                return true;
            }
            if(line.size()>MAX_LINE)
            {
                _resp_statu=414;//请求实体过长
                _recv_statu=RECV_HTTP_ERR;
                    return false;
            }
            int ret=ParseHttpHead(line);
            if(ret==false)
                return false;
        }
            _recv_statu=RECV_HTTP_BODY;
            return true;
        }
        bool ParseHttpHead(std::string&line){
            if(_recv_statu!=RECV_HTTP_HEAD)return false;
            if(line.back()=='\n')line.pop_back();
            if(line.back()=='\r')line.pop_back();
            size_t pos=line.find(": ");
            if(pos==std::string::npos){
                _recv_statu=RECV_HTTP_ERR;
                _resp_statu=400;//请求语法错误
                return false;
            }
            std::string key=line.substr(0,pos);
            std::string value=line.substr(pos+2);
            _request.SetHeader(key,value);
            return true;
        }
        bool RecvHttpBody(Buffer*buf){
            if(_recv_statu!=RECV_HTTP_BODY)return false;
            //获取正文长度
            size_t content_length=_request.ContentLength();
            if(content_length==0){
                    _recv_statu=RECV_HTTP_OVER;
                    return true;
                }
            size_t remainder=content_length-_request._body.size();//正文还差多少数据
            if(remainder<=buf->ReadAbleSize()){//缓冲区数据足以满足所需
                _request._body+=buf->ReadAsStringAndPop(remainder);
                _recv_statu=RECV_HTTP_OVER;
            }
            else 
                _request._body+=buf->ReadAsStringAndPop(buf->ReadAbleSize());
            return true;
        }
    public:
        HttpContext():_recv_statu(RECV_HTTP_LINE),_resp_statu(200){}
        int ResponseStatus(){
            return _resp_statu;
        }
        HttpRecvStatu RecvStatus(){
            return _recv_statu;
        }
        HttpRequest& Request(){
            return _request;
        }
        void RecvHttpRequest(Buffer*buffer){//接受并解析HTTP请求
            switch(_recv_statu){
                case RECV_HTTP_LINE:RecvHttpLine(buffer);
                case RECV_HTTP_HEAD:RecvHttpHead(buffer);
                case RECV_HTTP_BODY:RecvHttpBody(buffer);
                default:break;
            }
        }
        void ReSet(){
            _recv_statu=RECV_HTTP_LINE;
            _request.ReSet();
            _resp_statu=200;
        }
};



class HttpServer{
    private:
        using Handler=std::function<void(const HttpRequest&,HttpResponse*)>;
        using Handlers=std::vector<std::pair<std::regex,Handler>>;
        Handlers _get_route;//请求处理函数
        Handlers _post_route;//请求处理函数
        Handlers _put_route;//请求处理函数
        Handlers _delete_route;//请求处理函数
        std::string _basedir;//根目录
        TcpServer _server;//服务器
    private:
    void ErrorHandler(const HttpRequest&request,HttpResponse*response){
        //组织一个错误展示页面
        std::string body="<!DOCTYPE html><html><head><title>Error</title></head><body><h1>Error</h1><p>HTTP/1.1 ";
        body+=std::to_string(response->_statu)+" "+Util::StatuDesc(response->_statu)+"</p></body></html>";
        //将页面数据当作相应正文放入response
        response->SetContent(body,"text/html");
        }
        //将response按照http协议格式写入缓冲区
        void WriteResponse(const PtrConnection&conn,HttpRequest&request,HttpResponse&response){
            //完善头部字段
           

            if(request.Close())
            {
                response.SetHeader("Connection","close");
            }
            else
                response.SetHeader("Connection","keep-alive");
            if(response._body.empty()==false&&response.HasHeader("Content-Length")==false)
                response.SetHeader("Content-Length",std::to_string(response._body.size()));
            if(response._body.empty()==false &&response.HasHeader("Content-Type")==false)
                response.SetHeader("Content-Type","application/octet-stream");
            if(response._redirect_flag){
                response.SetHeader("Location",response._redirect_url);
            }
            std::string str;
            str+=request._version+" "+std::to_string(response._statu)+" "+Util::StatuDesc(response._statu)+"\r\n";
            for(auto s:response._headers)
            str+=s.first+": "+s.second+"\r\n";
            str+="\r\n";
            str+=response._body;
            conn->Send(str.c_str(),str.size());
        }
        //判断是不是静态资源的请求
         bool IsFileHandler(const HttpRequest&request){
            //必须设置了静态资源根目录，
            if(_basedir.empty())return false;
            //请求方法必须是GET或HEAD
            if(request._method!="GET"&&request._method!="HEAD")return false;
            //请求路径必须合法
            if(Util::ValidPath(request._path)==false)return false;
            //请求的资源必须存在
            //对于请求目录的需求，我们把它设置为请求首页
            //后面可能进行功能性请求，所以不能直接修改path成员
            std::string path=_basedir+request._path;
            if(request._path.back()=='/'){
                path+="index.html";
            }
            if(Util::IsRegular(path)==false){
                return false;
            }
            return true;
         }
         //静态资源的请求
        void FileHandler(const HttpRequest&request,HttpResponse*response){
            std::string path=_basedir+request._path;
            if(path.back()=='/')
            path+="index.html";
            bool ret=Util::ReadFile(path,&response->_body);
            if(ret==false)return ;
            std::string mime=Util::ExtMime(path);
            response->SetContent(response->_body,mime);
        }
        //功能性请求的分类处理
        void DisPatcher(HttpRequest&request,HttpResponse*response,Handlers&handlers){
            //使用正则表达式进行匹配
            for(auto&p:handlers){
                std::regex& e=p.first;
                Handler f=p.second;
                bool ret=std::regex_match(request._path,e);
                if(ret){
                   return  f(request,response);
                }
            }
            response->_statu=404;
        }
        //设置上下文
        void OnConnected(const PtrConnection&conn){
            conn->SetContext(HttpContext());
            DBG_LOG("NEW CONNECTION :%p",conn->Get());
        }
        //处理请求
        void Route( HttpRequest&request,HttpResponse*response){
            //判断是静态资源请求还是功能性请求
            //先看是不是静态资源请求
            if(IsFileHandler(request)==true){
                return FileHandler(request,response);
            }
            if(request._method=="GET"||request._method=="HEAD"){
               return  DisPatcher(request,response,_get_route);
            }
            else if(request._method=="POST"){
               return  DisPatcher(request,response,_post_route);
            }
            else if(request._method=="PUT"){
                return DisPatcher(request,response,_put_route);
            }
            else if(request._method=="DELETE"){
                return DisPatcher(request,response,_delete_route);
            }
                response->_statu=405;
            return;
        }
        //对缓冲区数据解析+处理
        void OnMessage(const PtrConnection&conn,Buffer*buffer){
            while(buffer->ReadAbleSize()>0){
            //获取上下文
            HttpContext*context=std::any_cast<HttpContext>(conn->Context());
            //通过上下文对缓冲区数据进行解析，得到httprequest对象
            context->RecvHttpRequest(buffer);
            HttpRequest&request=context->Request();
             HttpResponse response(context->ResponseStatus());
             
            //如果解析出错
            if(context->ResponseStatus()>=400){
                //进行错误相应，关闭连接
                ErrorHandler(request,&response);
                WriteResponse(conn,request,response);
                context->ReSet();//这一步必不可少！！！不更新会导致下次状态码是400，recv状态是RECV_HTTP_ERR,然后死循环
                buffer->MoveReadOffset(buffer->ReadAbleSize());//出错就清空，损失一点点数据换取效率和稳定性
                conn->ShutDown();
                return;
            }
            if(context->RecvStatus()!=RECV_HTTP_OVER){
                //当前请求不完整,等待新数据到来接着处理
                return;
            }
            
           
            //请求路由+业务处理
            Route(request,&response);
            //得到response对象并发送
            WriteResponse(conn,request,response);
            //重置上下文
            context->ReSet();
            //根据长短连接情况，关闭连接或保持连接
            if(response.Close())
            {
                // printf("close connection\n");
                conn->ShutDown();
            }
        }
    }
    public:
        HttpServer(int port,int timeout=DEFAULT_TIMEOUT):_server(port){
            //建立连接后设置上下文
            _server.SetConnectedCallBack(std::bind(&HttpServer::OnConnected,this,std::placeholders::_1));
            //缓冲区获取信息后进行处理
            _server.SetMessageCallBack(std::bind(&HttpServer::OnMessage,this,std::placeholders::_1,std::placeholders::_2));
            //设置超时时间
            _server.EnableInactiveRelease(timeout);
        }
        void SetBaseDir(const std::string&dir){
            bool ret=Util::IsDirectory(dir);
            assert(ret==true);
            _basedir=dir;
        }
        void Get(const std::string&pattern,const Handler& handler){
            _get_route.push_back(std::make_pair(std::regex(pattern),handler));
        }
        void Post(const std::string&pattern,Handler handler){
            _post_route.push_back(std::make_pair(std::regex(pattern),handler));
        }
        void Put(const std::string&pattern,Handler handler){
            _put_route.push_back(std::make_pair(std::regex(pattern),handler));
        }
        void Delete(const std::string&pattern,Handler handler){
            _delete_route.push_back(std::make_pair(std::regex(pattern),handler));
        }
        void SetThreadCount(int count){
            _server.SetThreadCount(count);
        }
        void Listen(){
            _server.Start();
        }
};